/*
 * DBConnector.java
 * iRoomMonitor1.0
 * 11/01/10
 */
package RoomNanny.SpotListener;

import java.text.DateFormat;
import java.io.*;
import java.util.*;

import iRoomMonitor.*;
/**
 * This class implements connecting to the database and holds all the
 * information needed to interface with the database and input the collected
 * data.
 *
 * @author Joe Granville
 */
public class DBConnector{
    public boolean connected;
    public static final String BACKUP_FILE = "backup.txt";
    public DB database;
    DateFormat fmt;
    String url;

    /**
     * This is the constructor for the DBConnector. It connects to the DB and
     * creates the backup file in case the DB is down.
     */
    public DBConnector(){
        database = new DB();
        connected = false;
        fmt = DateFormat.getTimeInstance();
        try{
        BufferedWriter out = new BufferedWriter(new FileWriter(BACKUP_FILE, false));
        out.write("");
        }
        catch (Exception e){
            System.err.println("failed to clear the backup file!");
        }
    }

    /**
     *
     * @param dbUrl
     * @throws Exception
     */
    public void connect(String dbUrl) throws Exception{
        url = dbUrl;
        if(!connected){
            try{
                DB.connect(dbUrl, "ES_API", "allmybase", false);
                connected = true;
            }
            catch (Exception e){
                System.err.println("No connection..." + e);
                connected = false;
            }
        }
    }

    /**
     * This method pushes the collected data to the database.
     *
     *
     * @param time
     * @param addr
     * @param spotIDReading
     * @param tempReading
     * @param state
     * @param lightReading
     * @param power
     * @throws Exception
     */
    public void push(long time, String addr, int spotIDReading, 
            double tempReading, int state, boolean lightReading,
            int power) throws Exception {
        try {
            if(!connected){
                System.out.println("Attempting to reconnect to the database");
                try{
                    connect(url);
                }
                catch(Exception e){
                    System.err.println("error reconnecting to database: " + e);
                }
                System.err.println("Connection reestablished; pushing catalogued data");

                 //code for dealing with a reconnect
                  String delims = "[ ]";
                  BufferedReader in = new BufferedReader(new FileReader(BACKUP_FILE));
                  String[] stuff;
                  String input;
                  while((input = in.readLine()) != null){
                  stuff = input.split(delims);
                  System.out.println("Pushing old data:" + input);
                  //so then: stuff is [2:58:51, PM, from:, 0014.4F01.0000.6452, (-2), temp, =, 69.80000000000001, light, =, true, Still]
                  String oldTime = stuff[0] + stuff[1]; //not needed for push
                  String address = stuff[3];
                  int id = java.lang.Integer.parseInt(stuff[4]);
                  if (id == -2){
                    id = register(address);
                  }
                   float temp = Float.valueOf(stuff[7].trim()).floatValue();
                   boolean light = java.lang.Boolean.parseBoolean(stuff[10]);
                   int doorInt = java.lang.Integer.parseInt(stuff[11]);
                   iRoomMonitor.DoorState door = getDoor(doorInt);
                   DB.pushBackupData(id, oldTime, temp, door, light);
                  }
                  in.close();
            }
            DB.pushData(spotIDReading, (float) tempReading, getDoor(state), lightReading);
            System.out.println("sending battery level: " + power);
            DB.updateBatteryStatus(spotIDReading, power);

        } catch (DBException e) {
            System.err.println("pushData failed, writing to flat file. Exception was: " + e);
            try {
                BufferedWriter out = new BufferedWriter(new FileWriter(BACKUP_FILE, true));
                out.write(fmt.format(new Date(time)) + " from: "
                + addr + " " + spotIDReading + " temp = " + tempReading
                + " light = " + lightReading + " "
                + state + "\n");
                out.close();
                connected = false;
            }
            catch (IOException writeException) {
                System.err.println("Write to backup file failed!");
            }

        }
    }

    /**
     * This method registers a Sunspot with the database.
     *
     * @param addr
     * @return int the assigned binary ID
     */
    public int register(String addr){
        try{
            if(connected){
                return database.registerSensor(addr);
            }
            else{
                connect(url);
                return database.registerSensor(addr);
            }
        }
        catch (Exception e){
            System.err.println("Unable to connect to DB, assigning error ID");
            System.err.println("DB connection returned error " + e);
            return -2;
        }
    }

    /**
     * This method changes the int parameters that were passed from the sensors
     * into the DoorState type that the database needs to store the information
     * @param door
     * @return DoorState
     */
    private DoorState getDoor(int door){

        switch(door){
                // Door closing
            case 0:
                return (DoorState.valueOf("Closing"));

                // door moving (this value is hardly used because cases 2 and 3
            case 1:
                return (DoorState.valueOf("Moving"));
                // Door Opening
            case 2:
                return (DoorState.valueOf("Opening"));
                // Door still (no motion detected)
            case 3:
                return (DoorState.valueOf("Still"));


        }
        return DoorState.valueOf("Still");
    }
}
